﻿using System.Collections.Generic;
using System.Linq;
using BPM.Web.Monitor.Filters;
using BPM.Web.Shared.Extensions;
using Furion;
using Furion.Extras.Admin.NET;
using Furion.Extras.Admin.NET.Options;
using Furion.Extras.Admin.NET.Service;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NeoSmart.Caching.Sqlite;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using OnceMi.AspNetCore.OSS;
using OpenTelemetry.Trace;
using Serilog;
using Yitter.IdGenerator;

namespace BPM.Web.Core;

public class Startup : AppStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddConfigurableOptions<RefreshTokenSettingOptions>();
        services.AddJwt<JwtHandler>(enableGlobalAuthorize: true);
        services.AddCorsAccessor();
        services.AddRemoteRequest();
        services.AddMvc()
            .AddMvcFilter<RequestActionFilter>()
            .AddNewtonsoftJson(options =>
        {
            // 首字母小写(驼峰样式)
            options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            // 时间格式化
            options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
            // 忽略循环引用
            options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            // 忽略空值
            // options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
        })
            .AddInjectWithUnifyResult<XnRestfulResultProvider>()
            .AddAppLocalization();  // 注册多语言;
        services.AddViewEngine();
        services.AddSignalR();
        services.AddResponseCompression(opts =>
        {
            opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
                new[] { "application/octet-stream" });
        });

        // 注册EventBus服务
        services.AddEventBus(builder =>
        {
            // 注册 Log 日志订阅者
            builder.AddSubscriber<LogEventSubscriber>();
        });

        if (App.Configuration["Cache:CacheType"] == "RedisCache")
        {
            services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = App.Configuration["Cache:RedisConnectionString"]; // redis连接配置
                options.InstanceName = App.Configuration["Cache:InstanceName"]; // 键名前缀
            });
        }
        else if (App.Configuration["Cache:CacheType"] == "SqliteCache")
        {
            services.AddSqliteCache(options => options.CachePath = @"./cache.db");
        }

        //// default minio
        //// 添加默认对象储存配置信息
        //services.AddOSSService(option =>
        //{
        //    option.Provider = OSSProvider.Minio;
        //    option.Endpoint = "oss.oncemi.com:9000";
        //    option.AccessKey = "Q*************9";
        //    option.SecretKey = "A**************************Q";
        //    option.IsEnableHttps = true;
        //    option.IsEnableCache = true;
        //});

        // aliyun oss
        // 添加名称为‘aliyunoss’的OSS对象储存配置信息
        services.AddOSSService("aliyunoss", option =>
        {
            option.Provider = OSSProvider.Aliyun;
            option.Endpoint = "oss-cn-hangzhou.aliyuncs.com";
            option.AccessKey = "L*******************U";
            option.SecretKey = "5*******************************T";
            option.IsEnableCache = true;
        });

        //// qcloud oss
        //// 从配置文件中加载节点为‘OSSProvider’的配置信息
        //services.AddOSSService("QCloud", "OSSProvider");

        if (App.Configuration["BlazorMode"] == "server")
        {
            services.AddServerSideBlazor();
            services.AddBpmBlazor(new Dictionary<string, object> {
                {"ServerUrl",App.Configuration["ServerUrl"] },
                {"ClientName",App.Configuration["ClientName"] },
                {"BlazorMode","server" }
            });
        }

        //OpenTelemetry APM
        services
            .AddProfileViewer()
            .AddOpenTelemetryTracing((builder)
                => builder
                    .AddSource("BPM.*")
                    .AddAspNetCoreInstrumentation()
                    .AddHttpClientInstrumentation()
                    .AddProfileViewExporter(builder => builder.AddFilter(new FileExtensionFilter("ico")))
            //.AddConsoleExporter()
         );
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseResponseCompression();
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseWebAssemblyDebugging();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            //app.UseHsts();
        }

        //  NGINX 反向代理获取真实IP
        app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
        });

        // 添加状态码拦截中间件
        app.UseUnifyResultStatusCodes();

        app.UseAppLocalization();

        //app.UseHttpsRedirection(); // 强制https
        app.UseStaticFiles();

        // Serilog请求日志中间件---必须在 UseStaticFiles 和 UseRouting 之间
        app.UseSerilogRequestLogging();

        app.UseRouting();

        app.UseCorsAccessor();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseInject();
        app.UseBootstrapBlazor();
        if (App.Configuration["BlazorMode"] == "server")
        {
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapBlazorHub();
                endpoints.MapProfileViewer();
                endpoints.MapHub<ChatHub>("/hubs/chathub");
                endpoints.MapControllerRoute(name: "areaRoute", pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
                endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
                endpoints.MapFallbackToPage("/_Host");
            });
        }
        else
        {
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapHub<ChatHub>("/hubs/chathub");
                endpoints.MapControllerRoute(name: "areaRoute", pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
                endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
                endpoints.MapFallbackToFile("index.html");
            });
        }
        app.UseBlazorFrameworkFiles();

        // 设置雪花Id的workerId，确保每个实例workerId都应不同
        YitIdHelper.SetIdGenerator(new IdGeneratorOptions { WorkerId = ushort.Parse(App.Configuration["SnowId:WorkerId"] ?? "1") });

        // 开启自启动定时任务
        App.GetService<ISysTimerService>().StartTimerJob();
    }
}
